package projecteuler;

import java.util.ArrayList;

public class Utils
{
    public static void doubleNumberInList(ArrayList<String> digits)
    {
        int carry = 0;
        int lengthOfArray = digits.size();
        for (int i = 0; i < lengthOfArray; i++)
        {
            int sum = Integer.parseInt(digits.get(i)) + Integer.parseInt(digits.get(i)) + carry;
            if (sum >= 10)
            {
                carry = 1;
                sum -= 10;
            }
            else
            {
                carry = 0;
            }
            digits.set(i, String.valueOf(sum));
        }
        if (carry > 0)
        {
            digits.add("1");
        }

        /*for (String s : digits)
        {
            System.out.print(s);
        }
        System.out.println();*/
    }

    public static ArrayList<String> add(ArrayList<String> term1, ArrayList<String> term2)
    {
        ArrayList<String> result = new ArrayList<String>();
        int carry = 0;
        int lengthOfTerm1 = term1.size();
        int lengthOfTerm2 = term2.size();
        int lengthOfArray = lengthOfTerm1 >= lengthOfTerm2 ? lengthOfTerm1 : lengthOfTerm2;
        for (int i = 0; i < lengthOfArray; i++)
        {
            int sum = (term1.size() > i ? Integer.parseInt(term1.get(i)) : 0) + (term2.size() > i ? Integer.parseInt(term2.get(i)) : 0) + carry;
            if (sum >= 10)
            {
                carry = 1;
                sum -= 10;
            }
            else
            {
                carry = 0;
            }
            result.add(String.valueOf(sum));
        }
        if (carry > 0)
        {
            result.add("1");
        }
        
        /*for (String s : result)
        {
            System.out.print(s);
        }
        System.out.println();*/
        
        return result;
    }
    
    public static void multiplyNumberBy(ArrayList<String> digits, int multiple)
    {
        int carry = 0;
        int lengthOfArray = digits.size();
        for (int i = 0; i < lengthOfArray; i++)
        {
            int sum = (Integer.parseInt(digits.get(i)) * multiple) + carry;
            carry = 0;
            if (sum > 10)
            {
                while (sum >= 10)
                {
                    carry += 1;
                    sum -= 10;
                }
            }
            else
            {
                carry = 0;
            }
            digits.set(i, String.valueOf(sum));
        }
        if (carry > 0)
        {
            String carryStr = String.valueOf(carry);
            for (int i = carryStr.length() - 1; i >= 0; i--)
            {
                digits.add(carryStr.substring(i, i+1));
            }
        }

        /*for (String s : digits)
        {
            System.out.print(s);
        }
        System.out.println();*/
    }

    public static ArrayList<String> multiplyNumberBy(ArrayList<String> digits, ArrayList<String> multiple)
    {
        int carry = 0;
        int lengthOfDigitsArray = digits.size();
        int lengthOfMultipleArray = multiple.size();
        ArrayList<String> result = new ArrayList<String>();
        ArrayList<ArrayList<String>> tempResults = new ArrayList<ArrayList<String>>();
        for (int i = 0; i < lengthOfDigitsArray; i++)
        {
            if (tempResults.size() <= i || tempResults.get(i) == null)
            {
                tempResults.add(new ArrayList<String>());
            }
            ArrayList<String> currentResults = tempResults.get(i);
            for (int k = 0; k < i; k++)
            {
                currentResults.add("0");
            }
            for (int j = 0; j < lengthOfMultipleArray; j++)
            {

                int sum = (Integer.parseInt(digits.get(i)) * Integer.parseInt(multiple.get(j))) + carry;
                carry = 0;
                if (sum > 10)
                {
                    while (sum >= 10)
                    {
                        carry += 1;
                        sum -= 10;
                    }
                }
                else
                {
                    carry = 0;
                }
                currentResults.add(String.valueOf(sum));
            }
            if (carry > 0)
            {
                String carryStr = String.valueOf(carry);
                for (int x = carryStr.length() - 1; x >= 0; x--)
                {
                    currentResults.add(carryStr.substring(x, x+1));
                }
                carry = 0;
            }
        }
        for (ArrayList<String> curRes : tempResults)
        {
            result = add(result, curRes);
        }
        return result;
        /*for (String s : digits)
        {
            System.out.print(s);
        }
        System.out.println();*/
    }

    public static ArrayList<Integer> getDivisors(int test)
    {
        ArrayList<Integer> divisors = new ArrayList<Integer>();
        divisors.add(1);
        for (int i = 2; i < test / 2; i++)
        {
            if (!divisors.contains(i))
            {
                if (test % i == 0)
                {
                    divisors.add(i);
                    divisors.add(test / i);
                }
            }
        }
        return divisors;
    }

    public static int getSumOfDivisors(int test)
    {
        ArrayList<Integer> divisors = Utils.getDivisors(test);
        int sumTestDivisors = 0;
        for (int i : divisors)
        {
            sumTestDivisors += i;
        }
        return sumTestDivisors;
    }

    public static int getAmicable(int a)
    {
        int b = Utils.getSumOfDivisors(a);
        int test = Utils.getSumOfDivisors(b);
        if (test == a && a != b)
        {
            return b;
        }
        return 0;
    }

    public static ArrayList<String> simplePower(ArrayList<String> digits, int exponent)
    {
        ArrayList<String> result = new ArrayList<String>();
        result = digits;
        for (int i = 1; i < exponent; i++)
        {
            result = multiplyNumberBy(result, digits);
        }
        return result;
    }
    
    public static ArrayList<String> power(ArrayList<String> digits, int exponent)
    {
        ArrayList<String> result = new ArrayList<String>();
        ArrayList<Boolean> instructions = new ArrayList<Boolean>();
        result = digits;
        while (exponent > 1)
        {
            if (exponent %2 == 0)
            {
                instructions.add(false);
                exponent = exponent / 2;
            }
            else
            {
                instructions.add(true);
                exponent -= 1;
            }
        }
        
        
        for (int i = instructions.size() -1; i >= 0; i-- )
        {
            Boolean b = instructions.get(i);
            if (b.booleanValue())
            {
                result = multiplyNumberBy(result, digits);
            }
            else
            {
                result = multiplyNumberBy(result, result);
            }
        }
        
        /*
        result = digits;
        for (int i = 1; i < exponent; i++)
        {
            result = multiplyNumberBy(result, digits);
        }*/
        return result;
    }
}
